package xj.graph2d;

import java.awt.BasicStroke;
import java.awt.Stroke;
import java.util.HashMap;
import java.util.Map;

public class StrokeMap {

  public static class StrokeAttr {
    public int width;

    public int cap;

    public int join;

    public int style;

    public StrokeAttr(int width, int cap, int join, int style) {
      this.width = width;
      this.cap = cap;
      this.join = join;
      this.style = style;
    }

    @Override
    public int hashCode() {
      return (width << 24) + (cap << 16) + (join << 8) + style;
    }

    @Override
    public boolean equals(Object obj) {
      if (obj != null && obj instanceof StrokeAttr) {
	StrokeAttr sa = (StrokeAttr) obj;
	return (width == sa.width && cap == sa.cap && join == sa.join && style == sa.style);
      } else {
	return false;
      }
    }

  }

  public static StrokeMap getInstance() {
    if (theInstance == null) {
      theInstance = new StrokeMap();
    }
    return theInstance;
  }

  public Stroke findStroke(int width) {
    return findStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER,
	DrawAttr.SOLID_LINE);
  }

  public Stroke findStroke(int width, int cap, int join) {
    return findStroke(width, cap, join, DrawAttr.SOLID_LINE);
  }

  public Stroke findStroke(int width, int cap, int join, int style) {
    if (debug) {
      System.out.println("findStroke():  width=" + width + "  cap=" + cap
	  + "  join=" + join + "  style=" + style);
    }

    StrokeAttr sa = new StrokeAttr(width, cap, join, style);
    Object o = map.get(sa);
    if (o instanceof Stroke) {
      return (Stroke) o;
    }

    if (debug) {
      System.out.println("new BasicStroke():  width=" + width + "  cap=" + cap
	  + "  join=" + join + "  style=" + style);
    }

    Stroke s;
    if (style == DrawAttr.SOLID_LINE) {
      s = new BasicStroke(width, cap, join);
    } else {
      if (width <= 1) {
	s = new BasicStroke(width, cap, join, 10.0f, dashPatterns[style], 0);
      } else {
	int len = dashPatterns[style].length;
	float[] dash = new float[len];
	for (int i = 0; i < len; i++) {
	  dash[i] = dashPatterns[style][i] + width - 1;
	}
	s = new BasicStroke(width, cap, join, 10.0f, dash, 0);
      }
    }
    map.put(sa, s);

    if (debug) {
      System.out.println("new BasicStroke(): s=" + s);
    }

    return s;
  }

  protected StrokeMap() {
  }

  protected static StrokeMap theInstance = null;

  protected Map<StrokeAttr, Stroke> map = new HashMap<StrokeAttr, Stroke>();

  protected static final float[][] dashPatterns = { null, { 8, 6 },
      { 8, 2, 2, 2 }, { 8, 2, 2, 2, 2, 2 }, { 2, 2 } };

  protected static final boolean debug = false;

}
